home *** CD-ROM | disk | FTP | other *** search
/ Collection of Tools & Utilities / Collection of Tools and Utilities.iso / edit / jwpsrc.zip / SEARCH.C < prev    next >
C/C++ Source or Header  |  1993-03-31  |  45KB  |  1,538 lines

  1. /* Copyright (C) Stephen Chung, 1991-1993.  All rights reserved. */
  2.  
  3. #include "jwp.h"
  4.  
  5.  
  6. #define EXPBLOCKSIZE        10
  7. #define CURLYINDICATOR      0xff
  8.  
  9.  
  10. typedef enum {
  11.     T_ERROR = 0, T_TEXT, T_ESCAPE,
  12.     T_SOFTRETURN, T_HARDRETURN, T_TAB,
  13.     T_MATCHALL, T_MATCHONE, T_MATCHKANJI, T_MATCHASCII, T_MATCHKANA,
  14.     T_COMMA, T_NOT, T_BOL, T_EOL, T_DASH,
  15.     T_OPENPAREN, T_CLOSEPAREN, T_OPENBRACKET, T_CLOSEBRACKET,
  16.     T_OPENCURLY, T_CLOSECURLY
  17. } TOKEN;
  18.  
  19. static struct { char ascii; TOKEN token; } tokens[] = {
  20.     { ',',      T_COMMA },
  21.     { '!',      T_NOT },
  22.     { '^',      T_BOL },
  23.     { '$',      T_EOL },
  24.     { '-',      T_DASH },
  25.     { '*',      T_MATCHALL },
  26.     { '?',      T_MATCHONE },
  27.     { '(',      T_OPENPAREN },
  28.     { ')',      T_CLOSEPAREN },
  29.     { '[',      T_OPENBRACKET },
  30.     { '[',      T_OPENBRACKET },
  31.     { ']',      T_CLOSEBRACKET },
  32.     { ']',      T_CLOSEBRACKET },
  33.     { '{',      T_OPENCURLY },
  34.     { '}',      T_CLOSECURLY },
  35.     { '\\',     T_ESCAPE },
  36.     { 0,        T_ERROR }
  37. };
  38.  
  39. static struct { char esc; TOKEN token; } escapes[] = {
  40.     { 'n',      T_SOFTRETURN },     /* \n */
  41.     { 'p',      T_HARDRETURN },     /* \p */
  42.     { 't',      T_TAB },            /* \t */
  43.     { 'x',      T_MATCHKANA },      /* \x */
  44.     { 'k',      T_MATCHKANJI },     /* \k */
  45.     { 'a',      T_MATCHASCII },     /* \a */
  46.     { '\0',     T_ERROR }
  47. };
  48.  
  49. static char *CompileErrors[] = {
  50.     /* 0 */     "The character after the escape character is missing",
  51.     /* 1 */     "Special characters (\p, \n etc.) cannot be placed within square brackets",
  52.     /* 2 */     "You can only put a NOT symbol right AFTER the open bracket",
  53.     /* 3 */     "The closing bracket is missing",
  54.     /* 4 */     "You must enter something to search for",
  55.     /* 5 */     "The range is not correct",
  56.     /* 6 */     "There must be character(s) inside a pair of brackets",
  57.     /* 7 */     "Curly brackets must enclose the digit 1 - 9",
  58.     /* 8 */     "",
  59.     /* 9 */     "Internal Error.  Life is tough."
  60. };
  61.  
  62.  
  63. typedef struct RegexStruct {
  64.     TOKEN action;
  65.     LONG data;
  66.     POSITION startpos, endpos;
  67.     struct RegexStruct far *prev, far *next;
  68. } REGEX;
  69.  
  70. static REGEX far *Expression = NULL;
  71. static KANJI far *ExpText = NULL;
  72.  
  73. static KANJI far *ReplaceExp = NULL;
  74. static KANJI far *ReplaceText = NULL;
  75.  
  76. static struct {
  77.     int IgnoreCase:1;
  78.     int Regex:1;
  79.     int JASCII:1;
  80.     int WrapAround:1;
  81.     int WholeFile:1;
  82.     int NoConfirm:1;
  83. } SearchOptions = { 1, 0, 1, 0, 0, 0 };
  84.  
  85. BOOL FAR PASCAL SearchProc (HWND, WORD, WORD, LONG);
  86. BOOL FAR PASCAL ReplaceProc (HWND, WORD, WORD, LONG);
  87. BOOL FAR PASCAL ReplaceDlgProc (HWND, WORD, WORD, LONG);
  88. BOOL FAR PASCAL EditReplacementProc (HWND, WORD, WORD, LONG);
  89.  
  90. static KANJI far *Replacement = NULL;
  91.  
  92.  
  93.  
  94. static int FindToken (KANJI token)
  95. {
  96.     int i;
  97.     char ch;
  98.  
  99.     token &= 0x7f7f;
  100.  
  101.     if (ISKANJI(token)) {
  102.         ch = LOBYTE(TranslateJAscii(token, TRUE));
  103.         if (!ch) return (-1);
  104.     } else {
  105.         ch = LOBYTE(token);
  106.     }
  107.  
  108.     for (i = 0; tokens[i].token != T_ERROR; i++) {
  109.         if (tokens[i].ascii == ch) return (i);
  110.     }
  111.     return (-1);
  112. }
  113.  
  114.  
  115. static int FindEscape (KANJI escape)
  116. {
  117.     int i;
  118.  
  119.     if ('A' <= escape && escape <= 'Z') escape += 32;
  120.  
  121.     for (i = 0; escapes[i].token != T_ERROR; i++) {
  122.         if (escapes[i].esc == escape) return (i);
  123.     }
  124.     return (-1);
  125. }
  126.  
  127.  
  128. static void FreeRegex (REGEX far *rp)
  129. {
  130.     REGEX far *rp2;
  131.  
  132.     if (rp == NULL) return;
  133.  
  134.     for (; rp != NULL; ) {
  135.         switch (rp->action) {
  136.             case T_TEXT:
  137.                 FreeBlock(rp->data);
  138.                 break;
  139.  
  140.             case T_NOT:
  141.             case T_OPENBRACKET:
  142.             case T_OPENPAREN:
  143.             case T_OPENCURLY:
  144.                 FreeRegex((REGEX far *) rp->data);
  145.                 break;
  146.  
  147.             default:
  148.                 break;
  149.         }
  150.  
  151.         rp2 = rp->next;
  152.         FreeBlock(rp);
  153.         rp = rp2;
  154.     }
  155. }
  156.  
  157.  
  158.  
  159. #define RETURN_WITH_ERROR(x,y)  { FreeRegex(RegexChain); RegexChain = NULL; *OutStr = InStr + (x); *ErrorNum = (y); return (NULL); }
  160.  
  161.  
  162. static REGEX far *CompileBracketedString (UNIT far *InStr, UNIT far **OutStr, int *ErrorNum, BOOL not)
  163. {
  164.     int i, j, k, errornum;
  165.     KANJI kch;
  166.     KANJI far *kp;
  167.     REGEX far *RegexChain = NULL, far *rp;
  168.  
  169.     for (i = 0; InStr[i].kanji; i++) {
  170.         kch = InStr[i].kanji;
  171.         j = FindToken(kch);
  172.         if (j >= 0) {
  173.             switch (tokens[j].token) {
  174.                 case T_CLOSEBRACKET:
  175.                     if (RegexChain == NULL) RETURN_WITH_ERROR(i, 6);
  176.  
  177.                     *OutStr = InStr + i;
  178.                     return (RegexChain);
  179.  
  180.                 case T_ESCAPE:
  181.                     kch = InStr[++i].kanji;
  182.                     if (!kch) RETURN_WITH_ERROR(i, 0);
  183.                     k = FindEscape(kch);
  184.                     if (k >= 0) RETURN_WITH_ERROR(i, 1);
  185.                     break;
  186.  
  187.                 case T_NOT: {
  188.                     REGEX far *rpx;
  189.                     UNIT far *up;
  190.  
  191.                     if (!not) RETURN_WITH_ERROR(i, 2);
  192.                     rpx = CompileBracketedString(InStr + i + 1, &up, &errornum, FALSE);
  193.                     i = up - InStr;
  194.                     if (rpx == NULL) RETURN_WITH_ERROR(i, errornum);
  195.  
  196.                     /* Adds to it */
  197.  
  198.                     if (RegexChain == NULL) {
  199.                         RegexChain = rp = StructAlloc(REGEX);
  200.                         rp->action = T_NOT;
  201.                         rp->data = (LONG) rpx;
  202.                         rp->next = rp->prev = NULL;
  203.                     } else {
  204.                         rp->next = StructAlloc(REGEX);
  205.                         rp->next->prev = rp;
  206.                         rp = rp->next;
  207.                         rp->next = NULL;
  208.                         rp->action = T_NOT;
  209.                         rp->data = (LONG) rpx;
  210.                     }
  211.  
  212.                     *OutStr = up;
  213.                     return (RegexChain);        /* Success! */
  214.                 }
  215.             }
  216.         }
  217.  
  218.         not = FALSE;
  219.  
  220.         if (j < 0 || tokens[j].token != T_DASH) {
  221.             j = FindToken(InStr[i+1].kanji);
  222.         } else {
  223.             kch = 0;
  224.             i--;    /* Because it is i += 2 later on */
  225.             goto ItIsADash;
  226.         }
  227.  
  228.         if (j >= 0) {
  229.             switch (tokens[j].token) {
  230.                 ItIsADash:
  231.                 case T_DASH: {
  232.                     KANJI start, stop;
  233.  
  234.                     start = kch;
  235.                     i += 2;
  236.                     stop = InStr[i].kanji;
  237.                     if (!stop) RETURN_WITH_ERROR(i, 3);
  238.  
  239.                     j = FindToken(stop);
  240.                     if (j >= 0 && tokens[j].token == T_CLOSEBRACKET) {
  241.                         stop = 0xffff;  /* Maximum value */
  242.                         i--;
  243.                     } else if (j >= 0 && tokens[j].token == T_ESCAPE) {
  244.                         stop = InStr[++i].kanji;
  245.                         if (!stop) RETURN_WITH_ERROR(i, 3);
  246.                         k = FindEscape(stop);
  247.                         if (k >= 0) RETURN_WITH_ERROR(i, 1);
  248.                     }
  249.  
  250.                     //if (ISKANJI(start) && !ISKANJI(stop)) RETURN_WITH_ERROR(i, ?);
  251.                     //if (!ISKANJI(start) && ISKANJI(stop)) RETURN_WITH_ERROR(i, ?);
  252.  
  253.                     if (start > stop) RETURN_WITH_ERROR(i, 5);
  254.                     if (start == stop) {
  255.                         kch = start;
  256.                         goto StraightText;
  257.                     }
  258.  
  259.  
  260.                     /* Adds to it */
  261.  
  262.                     if (RegexChain == NULL) {
  263.                         RegexChain = rp = StructAlloc(REGEX);
  264.                         rp->action = T_DASH;
  265.                         rp->data = MAKELONG(start,stop);
  266.                         rp->next = rp->prev = NULL;
  267.                     } else {
  268.                         rp->next = StructAlloc(REGEX);
  269.                         rp->next->prev = rp;
  270.                         rp = rp->next;
  271.                         rp->next = NULL;
  272.                         rp->action = T_DASH;
  273.                         rp->data = MAKELONG(start,stop);
  274.                     }
  275.                     continue;
  276.                 }
  277.  
  278.             }
  279.         }
  280.  
  281.         /* Now, just a normal character */
  282.  
  283. StraightText:
  284.  
  285.         if (RegexChain == NULL) {
  286.             RegexChain = rp = StructAlloc(REGEX);
  287.